Voici la fiche servant de trace écrite liée à ce chapitre qui est à compléter au cours de l'avancée.

Python : un langage interprété

Python est un langage de programmation développé à partir de 1989 par Guido van Rossum. photo de Van Rossum

Ce langage de programmation est :

Langage interprété ?

Dans un langage interprété : le code que vous écrivez est interprété en gros ligne à ligne, par un logiciel qu'on appelle interpréteur. Celui-ci va utiliser le code source et les données d'entrée pour calculer les données de sortie.

schéma de l'exécution d'un programme en langage interprété
source : http://data.france-ioi.org

D'autres langages (comme le C, ...) sont compilés : le code que vous écrivez est d'abord compilé par un logiciel qu'on appelle compilateur en une succession de 0 et de 1. Le système d'exploitation utilise ce code compilé ainsi que les données pour calculer les données de sorties.

schéma de l'exécution d'un programme en langage compilé
source : http://data.france-ioi.org

L'intérêt principal d'un langage interprété est la portabilité de votre programme : il marche quelle que soit la configuration de votre ordinateur.

Le principal défaut est que l'exécution d'un programme interprété est souvent plus lente que le même programme écrit dans un langage complié.

Pour plus d'information sur le langage Python, nous vous conseillons le site suivant : https://www.lebigdata.fr/python-langage-definition

Affectation

Pendant l’exécution d’un programme, les données que ce dernier manipule sont stockées en mémoire centrale. En nommant ces données, on peut les manipuler beaucoup plus facilement. Les variables nous permettent donc de manipuler ces données sans avoir à se préoccuper de l’adresse explicite qu’elles occuperont effectivement en mémoire. Pour cela, il suffit de leur choisir un nom ou identificateur.

  1. Les identificateurs sont des suites de lettres, de chiffres et de tirets bas (alt gr + 8), le premier caractère ne pouvant être un chiffre.

  2. Attention à ne pas choisir comme identificateur des mots-clés ou de types comme for, int, ...

L’interpréteur est un programme qui traduit les lignes de code en langage Python en un langage directement compréhensible par l'ordinateur : le langage machine. L'interpréteur s’occupe d’attribuer une adresse à chaque variable et de superviser tous les éventuels futurs changements d’adresse.

En programmation, on manipule des variables. Les variables sont comme des boites qui porte un nom dans lesquelles on range ce que l'on souhaite. Si vous souhaitez plus de détails diriger vous vers le cours d'algorithmique A1_algorithmique, à la partie 2. (cf. Lien direct).

L'affection d'une donnée à une variable, c'est l'action de mettre en mémoire une donnée dans une variable.

Par exemple, l'action stocker 100 dans la variable pv_player correspond à l'affection des 100 points de vie dans la variable pv_player

Ceci signifie : « à l’adresse mémoire référencée par pv_player - autrement dit, dans la boîte aux lettres dénommée pv_player -, se trouve la valeur 100 ». Nous utilisons plus fréquemment l’abus de langage « la variable pv_player vaut 100 ».

illustration plus réaliste du concept de variable

Affecter l'entier 100 dans une variable nommée pv_player est noté en pseudo-code :

pv_player ← 100

En langage Python, l'opérateur d'affectation est le symbole égal : =.
On note ainsi l'affectation de 100 à pv_player : pv_player = 100

Attention ! En écrivant ceci, on n'exprime pas une égalité mais l'interpréteur exécute les actions suivantes :

Ainsi, en python, on peut lire pv_player = 100 comme : "pv_player est lié à un objet de type int dont la valeur est 100".

Même si Python est un langage non typé, on peut tout de même préciser le type directement ainsi : pv_player:int = 100.

De même, l'instruction

>>>x = x+1

est très fréquente en informatique en revanche, elle est inacceptable en mathématiques.

De plus, à chaque variable correspond un identifiant, un numéro qui identifie une case mémoire. En Python, il est possible de connaître :

  1. Saisir le code suivant :

    pv_player = 100
    id(pv_player)
  2. Est-ce que chacun d'entre vous à le même identifiant à l'issue de l'exécution de ce code ?

  3. Saisir le code suivant :

    pv_player2 = pv_player
    id(b)

    Que remarquez-vous sur l'identifiant de pv_player2 ?

  4. Déterminer, grâce à l'instruction type le type de la variable pv_player.

  5. Saisir le code suivant :

    name_player = "Rage"

  6. Déterminer l'identifiant et le type de la variable name_player. Qu'en déduisez-vous ?

  7. Saisir le code suivant :

    ig_player = True

  8. Déterminer le type de la variable ig_player. Qu'en déduisez-vous ?

Code de déblocage de la correction :

  • L'affectation se fait en Python à l'aide du symbole =.

  • en Python, on copie en fait des adresses mémoire, pas des valeurs.

  • en Python, on peut réaffecter une valeur d'un autre type à une variable.

Affichage et saisie

Affichage

La fonction print permet d'afficher les éléments mis entre parenthèses.

Tester l'instruction suivante :

print("Salut tout le monde !")

La fonction print peut prendre plusieurs arguments séparés par une virgule ,
Cela permet ainsi d'afficher un mélange de texte et de contenu de variables.

Tester l'instruction suivante :

a=25
print("Cette année, Noël sera le",a,"décembre ! Incroyable! Amazing ! Dingue! Breaking News !")

Concaténation

Vous avez dû remarquer avec l'exemple précédent qu'à l'exécution, un espace ' ' ou " " est automatiquement ajouté entre chaque argument de la fonction print.
On peut améliorer l'affichage en utlisant l'opérateur de concaténation +.

Tester l'instruction suivante :

name_player = "Rage"
pv_player = 100
print("Tu te nommes " + name_player + " et tu as :" , pv_player , "points de vie.")

Transformer les espaces

Vous avez dû remarquer avec l'exemple précédent qu'à l'exécution, un espace ' ' ou " " est automatiquement ajouté entre chaque argument de la fonction print.
Ce comportement peut être modifié par l'ajout d'un argument identifié par le nom sep, de type chaîne de caractères (str en Python).

Tester l'instruction suivante :

name_player = "Rage"
pv_player = 100
print("Tu te nommes ", name_player, " et tu as :", pv_player, "points de vie.", sep="_")

Aller à la ligne dans un print

Le chaîne de caractères \n sert à passer à la ligne lors de l'affichage. Ainsi, dans l'utilisation suivante, les arguments affichés sont placés les uns en dessous des autres :

Tester l'instruction suivante :

print("c'est ma première ligne \ncelle la la deuxième \net la troisième.")

Réaliser l'affichage suivant en n'utilisant qu'un seul \n :


Rage a assez
de vices
pour faire
du bricolage. 
                    
                    

Code de déblocage de la correction :

  • la fonction print("chaînes de caractères",'à','afficher',sep=' ') sert à afficher un ensemble de chaînes de caractères avec comme séparateur par défaut un espace.

  • \n, pour newline, sert à passer à la ligne (lors de l'affichage, ...)

Saisie

input

La fonction input permet d'obtenir une saisie depuis le clavier.

  1. Tester le code suivant :
  2. level_player=input("Quel est ton niveau ?")
    				
  3. Tester le code suivant :
  4. type(level_player)
    					
  5. Tester le code suivant :
  6. print("tu as gagné un niveau, tu es maintenant de niveau : ", level_player+1,".")
    					
    Pourquoi cet affichage ?

Code de déblocage de la correction :

Attention ! La fonction input renvoie toujours une chaîne de caractères (son type est bien str) même si un nombre (entier ou réel) a été saisi. Pour pouvoir utiliser le renvoi dans un calcul, il est parfois nécessaire de changer son typage à l'aide des fonctions int ou float qui permettent de transformer respectivement une chaîne de caractères correspondant à un nombre en nombre entier ou nombre réel (un flottant pour être précis).

  1. Tester le code suivant :
  2. level_player=int(input("Quel est ton niveau ?"))
    				
  3. Tester le code suivant :
  4. type(level_player)
    					
  5. Tester le code suivant :
  6. print("tu as gagné un niveau, tu es maintenant de niveau : ", level_player+1,".")
    					

Code de déblocage de la correction :

  • input("texte") permet de saisir une information, sous forme de chaîne de caractères (=texte), pour un programme.

  • Il faudra éventuellement convertir ce texte dans le type voulu avec les instructions int() ou float().

Les fonctions

Notion

Fonctions en informatique

En informatiques, les fonctions servent à mieux structurer votre code. Par exemple, elles permettent d'éviter de répéter plusieurs fois des portions de codes identiques. Ainsi, une fonction peut être vu comme un «petit» programme :

Une fonction qui modifie des variables mais sans renvoyer de résultat est appellée une procédure. Le langage Python ne fait pas de différence dans la syntaxe entre fonction et procédure.

vision naîve d'une fonction en informatique

Une fonction qui renvoie un booléen est aussi appelé un prédicat.

En Python

Fonctions en Python

En Python, une fonction est définie (= être créée) en suivant toujours le même formalisme :
  1. Commencer par le mot clé def,
  2. Poursuivre sur la même ligne par l'entête constituée des 3 éléments successifs suivants :
    1. le nom de la fonction
    2. entre parenthèses, de 0 à N paramètres avec pour chacun un nom
    3. Terminer obligatoirement la première ligne par deux points :
  3. En dessous, écrire le blocs des instructions. Attention il faut indenter (=décaler) ce bloc !
  4. Finir en dernière ligne par le mot clé return suivi de ce que renvoie la fonction (ou None si la fonction ne retourne rien). Attention, cette ligne est indentée également et marque la fin de la fonction.

Voici visuellement la structure d'une fonction en Python :

def nomFonction(liste des arguments):
	blocs des instructions
	return résultat

Voici la fonction move_pv :

def move_pv(pv_player, attaque) :
    pv_player=pv_player-attaque
	return pv_player 		# renvoie le nouveau nombre de pv du joueur
			

Appel de fonction

Une fonction est utilisée comme une instruction quelconque. Un appel de fonction est constitué du nom de la fonction suivi entre parenthèses des valeurs des paramètres d'entrée. Cet appel peut être fait :

Rage récolte du bois. Il en ramasse une grande quantité. Dans son inventaire, il ne peux faire des piles (stack en anglais) uniquement de 500 morceux de bois. On aimerait disposer d'une fonction qui renvoie le nombre de piles complètes et le niveau de remplissage du dernier stack.

  1. Écrire une fonction stacking(dropped) qui a une quantié d'objets ramassés dropped renvoie le nombre de piles à 500 élements et le nombre de morceaux de la dernière pile incomplète.
    Par exemple stacking(1232) renvoie 2,232, 2 stacks à 500 morceaux de bois et un stack de 232 morceaux de bois.

    Il peut vous être utile d'utiliser les deux opérateurs // et % définis ainsi :

    • a // b renvoie le quotient de la division euclidienne de a par b.

      13 // 5 renvoie 2 car $13 = 5 \times 2 + 3$.

    • a % b renvoie le reste de la division euclidienne de a par b.

      13 % 5 renvoie 3 car $13 = 5 \times 2 + 3$.

  2. Appeler cette fonction afin de stacker 15352 morceaux de bois.

Code de déblocage de la correction :

exercice de renforcement

Bonnes pratiques de programmation

Préciser le typage de chacun des paramètres

Le langage Python est plus aisé pour démarrer la programmation pour la concision des codes écrits et pour la gestion automatique du typage par l'interpréteur. Cependant, le but est que vous puissiez à terme être capable de faire basculer vos compétences acquises en NSI sur Python vers d'autres langages de programmation.

Comme la plupart des langages de programmation nécessitent la spécification du typage des variables, à terme, on vous demandera d'écrire en Python, une fonction en précisant le type de chaque antrée et sortie en suivant le même formalisme que ci-dessous :

def nom_fonction(liste des arguments: type) -> typeRetour:
	blocs des instructions
	return résultat
	

La convention PEP8 donne l'habitude de nommer les fonctions (comme les variables) avec des lettres minuscules des soulignés bas (touche du "8") _. Pour clarifier la fonction, il est conseillé d'utiliser un verbe dans son nom (obtenir, donner, get, set, ...).

def set_pv(pv_player : float , attaque : int)-> float:
    pv_player=pv_player-attaque
	return pv_player 		
			
Documenter ses fonctions

Il est important de documenter vos fonctions, c'est-à-dire de décrire en quelques phrases le rôle de la fonction, de donner des informations sur la fonction, le lien entre les entrées et la sortie.

Pour cela, juste en dessous de la première ligne définissant la fonction, il suffit de mettre ses informations entre """ et """ ; c'est ce que l'on appelle en franglais le docstring de la fonction). En reprenant l'exemple précédent (sans le typage), on peut écrire :

def set_pv(pv_player : float , attaque : int)-> float:
    """
    Renvoie le nombre de point de vie du joueur auquel on retire la valeur contenu dans la variable attaque.
    """
    pv_player=pv_player-attaque
	return pv_player 		
			

L'intérêt de l'auto-documentation d'une fonction par un texte est double :

help

Quand on saisit dans la console, après l'exécution de la fonction, l'instruction help(nom de la fonction), Python affiche le docstring de la fonction ce qui nous permet d'avoir des informations sur la fonction en cas d'oubli.

>>> help(set_pv)
Help on function set_pv in module __main__:
				
set_pv(pv_player : float , attaque : int)-> float
	Renvoie le nombre de point de vie du joueur auquel on retire la valeur contenu dans la variable attaque.		
>>>

Voici ci-dessous une fonction qui renvoie le niveau d'armure du joueur en disposant comme argument le niveau d'armure base_armor et le niveau d'usure de l'armure armor_damage exprimé en pourcentage.


def set_armor(base_armor,armor_damage):
    armor = base_armor * (1 - armor_damage/100)
	return armor
					

Améliorer le code précédent en préciser le typage de chaque paramètre et en documentant cette fonction.

Code de déblocage de la correction :

exercice de renforcement

Utilisation de modules

Nous avons déjà vues les fonctions print et input. Ce sont deux fonctions prédéfinies dans le langage Python, On appelle ce type de fonction des fonctions natives au langage Python , elles sont directement utilisables.

D'autres fonctions ont été développées et testées par différents programmeurs mais ne sont pas directement utilisables. Ces fonctions sont regroupées dans des modules, appelés aussi bibliothèques. En terminale, vous apprendrez même à en créer par vous même !

Pour pouvoir utiliser ces fonctions, il faut d'abord importer ces modules. Pour cela, il y a plusieurs méthodes :

La portée des variables

Il faut faire la différence entre les variables utilisées dans le programme (variables globales) et les variables utilisées dans une fonction (variables locales).

Vous allez comprendre cela à l'aide des exemples de l'exercice suivant :

Réaliser des appels des trois fonctions suivantes pour comprendre la différence entre leurs codes :

  1. 
    pv_player=100
    def set_pv_1(pv_player,attack):
    	pv_player=pv_player-attack
    	return pv_player
    print(set_pv_1(50,25))
    
  2. 
    pv_player=100
    def set_pv_2(attack):
        pv_player=pv_player-attack
    	return pv_player
    print(set_pv_2(25))
    
  3. 
    pv_player=100
    def set_pv_3(attack):
    	global pv_player
    	pv_player=pv_player-attack
    	return pv_player
    print(set_pv_3(25))
    

Code de déblocage de la correction :

exercice de renforcement

Normalement vous avez dû détecter un problème : il y a une fonction qui ne peut pas être interprétée !

Il faut privilégier les variables locales. La première écriture, celle de set_pv est la définition à privilégier.

Vous pouvez utiliser des variables globales, comme mais dans set_pv_3, des cas qu'il faudra bien définir en amont.

Le danger des variables globales est qu'elles peuvent être modifiées à différents endroits d'un programme ce qui rend plus difficile la prévision du comportement du programme, dès que celui-ci devient assez conséquent.

Le seule moment où on devra utiliser les varaibles globalse , c'est à la construction de jeu ( ou autre appli ) en programmation itérative (celle de première).

  1. Voici une fonction set_score qui prend comme paramètre d'entrée les points à rajouter et renvoie le nouveau score obtenu.

    def set_score(points: int) -> int:
    	"""
    	fonction qui renvoie le score du nombre de points donnés comme entrée
        paramètres :
            points : nombre de points à rajouter à la variable globale score (nombre entier)
        retour : 
            score : nombre de points du score (nombre entier)
        """	
    	global score
    	score = score + points
    	return score
    

    Combien de variables apparaissent dans la fonction set_score ? De quel type ?

  2. Exécuter le script suivant :

    score = 100
    def set_score(points: int) -> int:
    	"""
    	fonction qui renvoie le score du nombre de points donnés comme entrée
    	paramètres :
    		points : nombre de points à rajouter à la variable globale score (nombre entier)
    		retour : 
    		score : nombre de points du score (nombre entier)
    	"""	
    	global score
    	score = score + points
    	return score
    
    for parties in range(1,4):				# 3 répétitions de l'affichage suivant
    	print("J'ai gagné 10 points ! set_score(10) affiche :",set_score(10))
    

    Est-ce que les appels set_score(10) renvoie toujours la même valeur ?

  3. Comme il est préférable d'éviter les variables globales, proposer une modification de la fonction set_score afin de supprimer la ligne global score.

    Rajouter un paramètre à la fonction peut-être très utile pour supprimer une variable globale.

  4. Tester le script complet précédent avec la fonction set_score modifiée.

Code de déblocage de la correction :

  • La structure générale d'une fonction :

    def nom_fonction(liste des arguments: type) -> typeRetour:
        blocs des instructions
        return résultat
    
  • L'indentation permet de définir ce qui fait partie de la fonction de ce qui en est exclu.

  • Une fois une fonction définie, pensez à l'appeler pour l'utiliser.

  • Toujours terminer une fonction par un return qui doit être pour le mieux unique.

  • Essayer de préciser les types des paramètres et du retour dans l'en-tête d'une fonction.

  • Essayer de documenter ses fonctions : texte explicatif entre triples guillements ou apostrophes.

  • Essayer d'éviter l'utilisation de variables globales.

Précondition et postconditions en Python

Précondition

Voici le code en Python d'une fonction nommée get_unite qui prend comme paramètre un nombre entier et qui renvoie son chiffre des unités.

def get_unite(n: int) -> int:
	"""
	renvoie le chiffre des unités d'un entier n
	"""
	while n>=10 : 		# répétition tant que n est supérieur ou égal à 10
		n = n-10
	return n

Une documentation a été donnée afin d'expliciter le bon usage de la fonction. Mais on ne pas être certain qu'un utilisateur de la fonction respectera les contraintes implicites ou explicites de la documentation et du typage. Voici quelques exemples d'appel de la fonction :


>>> get_unite(4567)
7
>>> get_unite(45.67)
5.670000000000002
>>> get_unite(-6)
-6

On voit que l'appel conduit à une réponse à chaque fois, mais que celle-ci ne correspond pas toujours à ce qui est attendu. Pour rendre "robuste" la fonction précédente, on doit vérifier au début de celle-ci certaines contraintes de bon usage que l'on appelle précondition.

Une précondition est une propriété (sur le type, sur les valeurs possibles, ...) vérifiée au début de l'exécution d'une fonction.

Dans l'exemple précédent, ces préconditions sont :

Pour cela, le langage Python possède l'instruction assert qui permet un mécanisme d'assertion.
Les deux préconditions précédentes s'ajoutent à la fonction précédente ainsi :

def get_unite(n: int) -> int:
	"""
	renvoie le chiffre des unités d'un entier n
	"""
	assert type(n)==int, "vous devez entrer un nombre entier."  		# "Précondition 1"
	assert n>=0, "le nombre étudié doit être positif ou nul."			# "Précondition 2"
	while n>=10 : 		# répétition tant que n est supérieur ou égal à 10
		n = n-10
	return n

Quelques explications :

assert

L'instruction assert teste sa condition. Deux cas possibles :

  1. si la condition est satisfaite, elle ne fait rien (l'interpréteur passe à la ligne suivante)
  2. sinon elle arrête immédiatement l'exécution du programme en affichant la phrase qui lui est éventuellement associée. Ainsi, l'interpréteur arrête l'exécution de la fonction plutôt que de faire planter le programme et affiche un message clair pour corriger l'erreur !

Vous pouvez retrouver ici une petite vidéo qui synthétise les appels de modules, les docstring et les assert

Voici un fonction nommée diviser réalisation la division du premier argument par le second.

def diviser(a: float,b: float) ->float:
	"""
	renvoie le résultat décimal de la division de a par b.
	"""
	return a/b

Quelle précondition, écrite en langage Python, doit-on rajouter afin d'assurer le bon fonctionnement de la fonction ?

Code de déblocage de la correction :

exercice de renforcement

Postcondition

Souvent les fonctions sont appelées au cours de programme ; le type et la qualité du résultat renvoyé sont importants pour ne pas conduire à un plantage. Des contraintes sur la variable renvoyée sont souvent nécessaires : on les appellent les postconditions.

Une postcondition est une propriété (sur le type, sur les valeurs possibles, ...) vérifiée à la fin de l'exécution d'une fonction.

Reprenons l'exemple précédent :

def get_unite(n: int) -> int:
"""
renvoie le chiffre des unités d'un entier n
"""
while n>=10 : 		# répétition tant que n est supérieur ou égal à 10
	n = n-10
return n

Voici le résultat de quelques appels effectués :


>>> get_unite(4567)
7
>>> get_unite(45.67)
5.670000000000002
>>> get_unite(-6)
-6

Comme le résultat renvoyé doit être un nombre entier compris entre 0 et 9, on va rajouter les postconditions suivantes :

  1. "postcondition 1" : n est un entier naturel.
  2. "postcondition 2" : n est positif.
  3. "postcondition 3" : n est strictement inférieur à 10

On utilise encore l'instruction assert, juste avant le return pour écrire ces postconditions comme montré ci-dessous :

def get_unite(n: int) -> int:
	"""
	renvoie le chiffre des unités d'un entier n
	"""
	while n>=10 : 		# répétition tant que n est supérieur ou égal à 10
		n = n-10
	assert type(n)==int, "Le nombre renvoyé devrait être un entier."  		# "Postcondition 1"
	assert n>=0, "le nombre renvoyé doit être positif ou nul."				# "Postcondition 2"
	assert n<10, "le nombre renvoyé doit être inférieur à 10."				# "Postcondition 3"
	return n
	

exercice de renforcement

  • Une précondition est une propriété vérifiée au début de l'exécution d'une fonction.

  • Une précondition est une propriété vérifiée à la fin de l'exécution d'une fonction.

  • Dans le langage Python, une pré/postcondition commence par le mot-clé assert.

  • Une telle instruction assert est suivie :

    1. d'une condition, qui vaut True ou False,

    2. éventuellement suivie d'une virgule , et d'une phrase en langue naturelle, sous forme d'une chaine de caractères.

  • L'instruction assert teste la condition. Deux cas possibles :

    1. si la condition est satisfaite, l'interpréteur passe à la ligne suivante,

    2. sinon elle arrête immédiatement l'exécution du programme en affichant la phrase qui lui est éventuellement associée. Ainsi, l'interpréteur arrête l'exécution de la fonction plutôt que de faire planter le programme et affiche un message clair pour corriger l'erreur !

Suivre l'état des variables pas à pas : Python Tutor

Quand on fait de la programmation, il est parfois utile pour comprendre un programme de réaliser un état des variables en cours d'execution.

Dans le cours A1 cette notion de trace d'execution est travaillé de manière approfondi.

Une solution numérique (plus simple qu'une trace d'execution au sens du cours A1) est proposée sur le Pythontutor.

Tester cette procédure avec Pythontutor :

def letter_by_letter(ch):
	for elt in ch : 
        print(elt)

letter_by_letter("Une société écologique, c'est une société qui trouve le point d'équilibre entre la société matérialiste absolue dans laquelle nous sommes et une société qui voudrait tomber dans une spiritualité béate qui ne serait pas plus intéressante.")
	

Des exercices

Fonction

L'Indice de Masse Corporelle (IMC)est un nombre réel utilisé en médecine. Sa formule est pour une $masse$ en kilos et une $taille$ en mètres : $IMC = \frac{masse}{taille^2}$.

  1. Écrire en langage Python dans Jupyter un programme qui :

    • Demande la masse de l'utilisateur en kg (nombre réel).

    • Demande la taille de l'utilisateur en cm (nombre entier).

    • contient une "fonction" de paramètres masse et taille.

    • "fonction" qui affiche l'IMC de l'utilisateur.

  2. La "fonction" intégrée est-elle une fonction ou une procédure ? Pourquoi ?

  3. Vérifier qu'une personne de 80 kg mesurant 1 mètre 80 a un IMC proche de 24.691358024691358.

Code de déblocage de la correction :

exercice de renforcement

Fonction

  1. Écrire une fonction saisir_nom qui ne prend pas de paramètre mais renvoie le nom saisi par l'utilisateur comme chaîne de caractères.

  2. Est-ce une fonction ou une procédure ? Pourquoi ?

  3. Écrire une fonction nommée dire_bonjour ayant comme paramètre un mot qui affiche bonjour suivi du mot.
    Exemple : dire_bonjour("Paul") affiche "Bonjour Paul !".

  4. Est-ce une fonction ou une procédure ? Pourquoi ?

  5. Proposer un programme qui :

    • intègre d'abord les deux fonctions précédentes,

    • qui utilise ces deux fonctions dans le corps principal du programme

    Ce programme :

    • Demande à l'utilisateur son nom.

    • Affiche Bonjour suivi du nom de la personne.

Code de déblocage de la correction :

exercice de renforcement

Précondition

Reprise de l'algorithme obtenu à l'exercice 4 du chapitre A1 (cf. Lien vers l'énoncé initial).

  1. Écrire une fonction nommée get_moyenne qui renvoie la moyenne de trois nombres quelconques passés en arguments.
  2. Proposer une précondition portant sur chacun des paramètres d'entrée pour assurer que la possibilité de calculer la somme.

Code de déblocage de la correction :

exercice de renforcement

Fonction

Reprise de l'algorithme obtenu à l'exercice 11 du chapitre A1 (cf. Lien vers l'énoncé initial).
Écrire une fonction appelée echanger qui échange les valeurs de deux arguments a et b.
Par exemple, echanger("mot",12) renvoie (12,"mot").

La possibilité de stocker un entier dans une variable stockant initialement une chaîne de caractères est possible en Python car c'est un langage non typé : l'interpréteur gère automatiquement le typage. Attention ! Dans beaucoup d'autres langages de programmation, cela n'est pas possible.

Code de déblocage de la correction :

Précondition
  1. Documenter la fonction suivante en ajoutant un docstring.

    def examen(x,y,z,t):
    	m=(2*x+2*y+z+t)/6
    	if m>=10:
    		print("Le candidat est reçu")
    	else :
    		print("le candidat est refusé")
    	return None
    
  2. Proposer des préconditions écrites sur les variables x, y, z et t en utilisant l'instruction assert qui assurent le bon usage de cette fonction examen.

Code de déblocage de la correction :

exercice de renforcement

Fonction

Voici une fonction cherche_lettre qui affiche si le caractère lettre est présent ou non dans le nom saisi nom, tout deux entrés comme paramètre de la fonction :

def cherche_lettre(nom,lettre):
	if lettre in nom:
		print(lettre," est dans le nom ",nom)
	else:
		print(lettre,"n' est pas dans le nom ",nom)
	return None 

  1. Préciser le type de chacun des paramètres d'entrée.

  2. Est-ce une fonction ou une procédure ?

  3. Proposer des préconditions écrites sur les variables nom et lettre en utilisant l'instruction assert qui assurent le bon usage de cette fonction cherche_lettre.

    La longueur d'une chaîne de caractères (c'est-à-dire le nomnbre de caractères) nommée chaine en Python s'obtient avec la commande len(chaine).

Code de déblocage de la correction :

exercice de renforcement

Travail complémentaire

Les exercices qui suivent nécessitent d'utiliser les instructions if, for ou while ainsi que des listes.

Reprise de l'algorithme obtenu à l'exercice 10 du chapitre A1 (cf. Lien vers l'énoncé initial).

Écrire une fonction get_max qui prend en paramètre une liste et renvoie le max des éléments de celle-ci.

Indications :

Code de déblocage de la correction :

Réécriture de l'algorithme obtenu à l'exercice 12 du chapitre A1 sous forme d'une fonction (cf. Lien vers l'énoncé initial).

  1. Écrire une fonction div_euclidienne qui prend en paramètre deux nombres entiers a et b, qui effectue la division euclidienne de a par b et qui renvoie le couple (a,i), respectivement le reste et le quotient de cette division euclidienne.

    Un tel couple est appelé tuple.

  2. Proposer des préconditions sur les paramètres a et b afin d'assurer le bon usage de la fonction div_euclidienne

    .
  3. Proposer des postconditions sur les deux valeurs renvoyées (a et i) afin d'assurer le bon usage de la fonction div_euclidienne

    .

Code de déblocage de la correction :

Réécriture de l'algorithme obtenu à l'exercice 16 du chapitre A1 sous forme d'une fonction (cf. Lien vers l'énoncé initial).

  1. Écrire une fonction get_max_position qui prend en paramètre une liste et qui renvoie le couple (le tuple) (PG,IG), respectivement la plus grande valeur de la liste et la position de cette valeur maximale dans la liste.

    Indications :

    • Une liste en python se note entre crochet [ ] chaque élément étant séparée d'une virgule.

    • la longueur d'une liste nommée liste en Python s'obtient avec la commande len(liste)

    • Chaque élément d'une liste est positionné à l'aide d'un index compris entre 0 et len(liste)-1.

    • L'élément d'une liste nommée liste positionné à l'index i est obtenu avec : liste[i].

  2. Proposer des postconditions sur la valeur renvoyée IG afin d'assurer le bon usage de la fonction get_max_position.

Code de déblocage de la correction :

Exercices de renforcement

L'ensemble des exercices de renforcement sont corrigés et expliqués dans le document Jupyter accessible avec ce lien.

On veut pouvoir convertir une durée en heures en une spéficiant le nombre de jours et le nombre d'heures correspondant. Pour cela, il suffit de créer une fonction.

  1. Définir une fonction convertir_jour qui prend comme paramètre un entier duree_heure en renvoie un tuple (=couple ici) formé des deux valeurs nb_jours et nb_heures.

  2. Appeler cette fonction afin de convertir en nombres de jours 260 heures.

Cliquer pour afficher la solution
  1. 
    def convertir_jour(duree_heure):
        nb_jours = duree_heure // 24
        nb_heures = duree_heure % 24
        return nb_jours,nb_heures
            
  2. convertir_jour(260) 

    L'appel renvoie (10,20)

Voici ci-dessous une fonction qui donne le prix TTC connaissant le prix Hors Taxe pour une TVA à t% :

def TTC(HT,t):
	TTC = HT * (1 + t/100)
	return TTC
		

Améliorer le code précédent en préciser le typage de chaque paramètre et en documentant cette fonction.

Cliquer pour afficher la solution

def TTC(HT: float,t: int) -> float:
    """
    fonction qui renvoie le prix TTC connaissant le prix Hors Taxe (HT) et la taux de TVA (t)
    HT est un nombre réel
    t est un entier compris entre 0 et 100
    """
    TTC = HT * (1 + t/100)
    return TTC

Parmi les scripts suivants, le(s)quel(s) peuvent correspondre à l'utilisation de la fonction inverse pour calculer l'image de 4 :

# script 1 :
x = 4
def fct1(x):
	x = 1/x
	return x

# script 2 :
x = 4
def fct2():
	x = 1/x
	return x

# script 3 :
def fct3(x):
	return 1/x

# script 4 :
x = 4
def fct4():
	global x
	x = 1/x
	return x
	
Cliquer pour afficher la solution

Un moyen d'estimer la profondeur d'un puits est de lâcher une pierre au dessus du puits et de compter le nombre de secondes avant d'entendre le bruit du "plouf" de son entrée dans l'eau. On note $t$ la durée d'attente du "plouf" (en seconde) et $p$ le profondeur du puits (en mètre).

On admet que les paramètres $t$ et $p$ sont liés par la relation physique suivante : $t=\sqrt{\frac{p}{4.9}}+\frac{p}{330}$.

  1. Première partie : une fois la notion précondition vue

    Proposer une fonction temps qui prend en paramètre la profondeur $p$ du puits et renvoie le temps $t$ d'attente du "plouf".

    Penser à importer la fonction sqrt du module math.

  2. Vérifier que l'on obtient l'affichage suivant pour l'exécution du script suivant :

    >>>temps(30)
    2.5652673874360583
    
  3. Rajouter à votre programme deux préconditions sur $p$.

  4. Seconde partie : une fois la notion postcondition vue

    Rajouter à votre programme une postcondition sur le valeur renvoyée.

  5. Rajouter une documentation à la fonction temps.

Cliquer pour afficher la solution
  1. 
    from math import sqrt
    def temps(p: float) -> float:
        t = sqrt(p / 4.9) + p / 330
        return t
    
  2. 
    temps(30)
    
    L'appel renvoie 2.5652673874360583
  3. 
    from math import sqrt
    def temps(p: float) -> float:
        assert type(p) == float, "Veuillez saisir un nombre réel comme argument de la fonction temps."
        assert p >= 0, "Veuillez saisir un nombre positif comme argument de la fonction temps."
        t = sqrt(p / 4.9) + p / 330
        return t
    
  4. 
    from math import sqrt
    def temps(p: float) -> float:
        assert type(p) == float, "Veuillez saisir un nombre réel comme argument de la fonction temps."
        assert p >= 0, "Veuillez saisir un nombre positif comme argument de la fonction temps."
        t = sqrt(p / 4.9) + p / 330
        assert t >= 0, "Le nombre renvoyé devrait être un nombre positif."
        return t
    
  5. 
    from math import sqrt
    def temps(p: float) -> float:
        """
        fonction donnant le temps nécessaire pour entendre le "plouf" d\'une pierre lâchée au-dessus d\'un puits de profondeur p
        entrée :
            p : nombre réel (profondeur du puits)
        sortie :
            t : nombre réel (temps d\'attente)
        """
        assert type(p) == float, "Veuillez saisir un nombre réel comme argument de la fonction temps."
        assert p >= 0, "Veuillez saisir un nombre positif comme argument de la fonction temps."
        t = sqrt(p / 4.9) + p / 330
        assert t >= 0, "Le nombre renvoyé devrait être un nombre positif."
        return t
    

L'énergie cinétique d'un objet de masse $m$ (en kg) qui se déplace à la vitesse $v$ (en $m.s^{-1}$) est donnée par la formule : $E_c=\frac{1}{2}\times m \times v^2$.

  1. Écrire une fonction nommée get_energie_cinetique ayant comme paramètres la masse m et la vitesse v qui renvoie l'énergie cinétique.

  2. Est-ce une fonction ou une procédure ? Pourquoi ?

  3. Quelle est l'énergie (en Joule) d'un objet de 3 kg se déplaçant à 1.56 $m.s^{-1}$ ?

Cliquer pour afficher la solution
  1. def get_energie_cinetique(m: float, v:float) -> float:
        """
        m est la masse d'un objet en kilogramme,
        v représente la vitesse de l'objet en m/s. 
        Cette fonction renvoie l'énergie cinétique de l'objet en Joule.
        """
        Ev = 1/2* m * v**2
        return Ev
        
  2. C'est une fonction car il y a un renvoi, ici d'un flotttant.

  3. get_energie_cinetique(3,1.56)
    renvoie 3.6504000000000003.
    L'énergie cinétique de l'ojet est d'environ 3.65 Joules.

  1. Écrire une fonction saisir_num_tel qui ne prend pas de paramètre mais renvoie le numéro de téléphone saisi par l'utilisateur comme chaîne de caractères.

  2. Est-ce une fonction ou une procédure ? Pourquoi ?

  3. Écrire une fonction nommée prevenir_message ayant comme paramètre un numéro de téléphone qui affiche "Vous allez recevoir un message de confimation au .........." où apparaît le numéro de téléphone saisi.
    Exemple : prevenir_message("0665432100") affiche "Vous allez recevoir un message de confimation au 0665432100.".

  4. Est-ce une fonction ou une procédure ? Pourquoi ?

  5. Intégrer ces deux fonctions pour faire apparaître un programme qui :

    • Demande à l'utilisateur son numéro de téléphone.

    • Affiche un message selon lequel un message de confirmation va être envoyé au numéro de la personne.

Cliquer pour afficher la solution
  1. 
    def saisir_num_tel() -> str:
        """
        fonction qui renvoie sous forme de chaîne de caractères le numéro de téléphone demandé à l'utilisateur
        """
        tel = input("Quel est votre numéro de téléphone ?")  # ne pas transtyper sous forme d'entier pour ne pas perdre le 0 du début.
        return tel
            
  2. Comme la fonction renvoie quelque chose, c'est bien une fonction et non une procédure.

  3. 
    def prevenir_message(num: str) -> None:
        """
        num est une chaîne de caractères correspondant à un numéro de téléphone.
        C'est procédure qui affiche un message en lien avec le numéro de téléphone saisi
        """
        print("Vous allez recevoir un message de confimation au",num)
            
  4. Comme la fonction ne renvoie rien, c'est bien une procédure.

  5. 
    numero = saisir_num_tel()
    prevenir_message(numero)
            

Reprise de l'algorithme obtenu à l'exercice 18 du chapitre A1 (cf. Lien vers l'énoncé initial).

  1. Écrire une fonction nommée get_moyenne5 qui renvoie la moyenne de cinq nombres quelconques passés en arguments.

  2. Proposer une précondition portant sur chacun des paramètres d'entrée pour assurer que la possibilité de calculer la somme.

Cliquer pour afficher la solution
  1. 
    def get_moyenne5(a: float,b: float,c: float,d: float,e: float) -> float:
        """
        a, b, c, d et e sont 5 nombres décimaux ou entiers.
        fonction qui renvoie la moyenne des cinq nombres saisis comme argument.
        """
        moy = (a+b+c+d+e)/5
        return moy
            
  2. 
    def get_moyenne5(a: float,b: float,c: float,d: float,e: float) -> float:
        """
        a, b, c, d et e sont 5 nombres décimaux ou entiers.
        fonction qui renvoie la moyenne des cinq nombres saisis comme argument.
        """
        # 5 préconditions rajoutées
        assert type(a) == int or type(a) == float, "tout argument saisi doit être un nombre"
        assert type(b) == int or type(b) == float, "tout argument saisi doit être un nombre"
        assert type(c) == int or type(c) == float, "tout argument saisi doit être un nombre"
        assert type(d) == int or type(d) == float, "tout argument saisi doit être un nombre"
        assert type(e) == int or type(e) == float, "tout argument saisi doit être un nombre"
        moy = (a+b+c+d+e)/5
        return moy
            

Reprise de l'algorithme obtenu à l'exercice 6 du chapitre A1 (cf. Lien vers l'énoncé initial).

Voici une écriture possible en langage Python de l'algorithme de cet exercice 6 sous forme de fonction :

def exo6(n):
	s = 0
	for i in range(1,n+1):
		s = s + i
	return s
		
  1. Documenter la fonction précédente en ajoutant un docstring et préciser le typage des paramètres.

  2. Proposer des préconditions écrites sur la variable n en utilisant l'instruction assert qui assurent le bon usage de cette fonction exo6.

  3. Proposer un postcondition écrite sur la variable renvoyée.

Cliquer pour afficher la solution
  1. 
    def exo6(n: int) -> int:
        """
        n est un nombre entier
        fonction qui renvoie la somme de tous les nombres entiers compris entre 0 et le nombre n saisi
        """
    	s = 0
    	for i in range(1,n+1):
    		s = s + i
    	return s
            
  2. 
    def exo6(n: int) -> int:
        """
        n est un nombre entier
        fonction qui renvoie la somme de tous les nombres entiers compris entre 0 et le nombre n saisi
        """
        # Ajout d'une précondition portant sur le type et sur la plage de valeurs possibles
        assert type(n) == int and n>=0, "l'argument saisi doit être un nombre entier positif"
    	s = 0
    	for i in range(1,n+1):
    		s = s + i
    	return s
            
  3. 
    def exo6(n: int) -> int:
        """
        n est un nombre entier
        fonction qui renvoie la somme de tous les nombres entiers compris entre 0 et le nombre n saisi
        """
        assert type(n) == int and n>=0, "l'argument saisi doit être un nombre entier positif"
    	s = 0
    	for i in range(1,n+1):
    		s = s + i
        # Ajout d'une postcondition portant sur le type et sur la plage de valeurs possibles pour la valeur renvoyée 
        assert type(s) == int and s>=0, "la valeur renvoyée devrait être un nombre entier positif"
    	return s
            

Reprise de l'algorithme obtenu à l'exercice 15 du chapitre A1 (cf. Lien vers l'énoncé initial).

Voici une écriture possible en langage Python de l'algorithme de cet exercice 15 sous forme de fonction :

def exo15(phrase,lettre):
	fin = ""
	for elt in phrase:
		if elt != lettre:
			fin = fin + elt
	return fin
		
  1. Documenter la fonction précédente en ajoutant un docstring et préciser le typage de chaque paramètre.

  2. Proposer des préconditions écrites sur les variables phrase et lettre en utilisant l'instruction assert qui assurent le bon usage de cette fonction exo15.

    L'instruction len(chaine) renvoie le nombre de caractères de la chaîne de cractères nommée chaine.

  3. Proposer un postcondition écrite sur la variable renvoyée.

Cliquer pour afficher la solution
  1. 
    def exo15(phrase: str,lettre: str) -> str:
        """
        phrase est une chaîne de caractères
        lettre est un unique caractère
        fonction qui renvoie la phrase initiale où tous les caractères lettre ont été ôtés.
        """
    	fin = ""
    	for elt in phrase:
    		if elt != lettre:
    			fin = fin + elt
    	return fin
            
  2. 
                            def exo15(phrase: str,lettre: str) -> str:
        """
        phrase est une chaîne de caractères
        lettre est un unique caractère
        fonction qui renvoie la phrase initiale où tous les caractères lettre ont été ôtés.
        """
        # ajout de deux préconditions portant sur le type et la longueur des arguments saisis
        assert type(phrase) == str, "le premier argument doit être une chaîne de caractères"
        asssert type(lettre) == str and len(lettre), "le second argument doit être une chaîne de caractères réduite à un seul caractère"
    	fin = ""
    	for elt in phrase:
    		if elt != lettre:
    			fin = fin + elt
    	return fin
            
  3. 
                            def exo15(phrase: str,lettre: str) -> str:
        """
        phrase est une chaîne de caractères
        lettre est un unique caractère
        fonction qui renvoie la phrase initiale où tous les caractères lettre ont été ôtés.
        """
        assert type(phrase) == str, "le premier argument doit être une chaîne de caractères"
        asssert type(lettre) == str and len(lettre), "le second argument doit être une chaîne de caractères réduite à un seul caractère"
    	fin = ""
    	for elt in phrase:
    		if elt != lettre:
    			fin = fin + elt
        # ajout d'une postcondition portant sur le type de la valeur renvoyée
        assert type(fin) == str, "la valeur renvoyée doit être une chaîne de caractères"
    	return fin
            

QCM

Questions issues de la Banque Nationale de Sujets

Propriétaire des ressources ci-dessous : ministère de l'Éducation nationale et de la jeunesse, licence CC BY SA NC

Voici une sélection de questions issues de la banque nationale de sujets, répondez à ces questions (attention, cette sélection n'est pas exhaustive).

On définit deux fonctions :

def f(x):
    y = 2*x + 1
    return y

def calcul(x):
    y = x - 1
    return f(y)
            

Quelle est la valeur renvoyée par l'appel calcul(5) ?

Réponses :

A- 4

B- 9

C- 11

D- 19

On exécute le code suivant

a = 2
b = 3
c = a ** b
d = c % b
            

Quelle est la valeur de d à la fin de l'exécution ?

Réponses :

A- 1

B- 2

C- 3

D- 4

On définit L = [2,3,5,7,-4].
En demandant la valeur de L[5], qu'obtient-on ?

Réponses :

A- -4

B- 2

C- 3

D- une erreur

On définit L = [4,25,10,9,7,13].
Quelle est la valeur de L[2] ?

Réponses :

A- 4

B- 25

C- 10

D- 9

En Python, quelle est la méthode pour charger la fonction sqrt du module math ?

Réponses :

A- using math.sqrt

B- #include math.sqrt

C- from math include sqrt

D- from math import sqrt

On exécute le script suivant :

def calcul(a,b):
    a = a + 2
    b = b + 5
    c = a + b
    return c

a,b = 3,5
calcul(a,b)

À la fin de cette exécution :

Réponses :

A- a vaut 3, b vaut 5 et c vaut 15

B- a vaut 3, b vaut 5 et c n'est pas défini

C- a vaut 5, b vaut 10 et c vaut 15

D- a vaut 5, b vaut 10 et c n'est pas défini

On exécute le script suivant :

def essai():
    a = 2
    b = 3
    c = 4
    return a
    return b
    return c

t = essai()

Quelle est la valeur de t après l'exécution de ce code ?

Réponses :

A- 2

B- 3

C- 4

D- (2,3,4)

La fonction suivante calcule la racine carrée du double d’un nombre flottant :

from math import sqrt
def racine_du_double(x):
    return sqrt(2*x)

Quelle est la précondition sur l'argument de cette fonction ?

Réponses :

A- x < 0

B- x >= 0

C- 2 * x > 0

D- sqrt(x) >= 0

Autres QCM

Les QCM suivants sont issus de https://genumsi.inria.fr.

(Auteur Nicolas Revéret)

On souhaite écrire un programme calculant le triple d'un nombre décimal et affichant le résultat. On a saisi le code suivant :

nombre = input("Saisir un nombre")
triple = nombre * 3
print(triple)

Un utilisateur saisit le nombre 5 lorsque l'ordinateur lui demande. Quel va être le résultat affiché ?

Réponses :

A- nombrenombrenombre

B- 555

C- 15

D- 15.0

(Auteur Nicolas Revéret)

On a saisi le code suivant :

nombre = int (input("Saisir un nombre") )
double = nombre * 2
print(double)

Quel message affiche l’ordinateur lorsque l'utilisateur saisit 8.5 ?

Réponses :

A- 16

B- 16.0

C- 17

D- L'ordinateur affiche une erreur

(Auteur Nicolas Revéret)

On a saisi le code suivant :

a = 8
b = 5
a = a + b
b = a - b
a = a - b

Quelles sont les valeurs de a et b à la fin du programme ?

Réponses :

A- a = 8 et b = 5

B- a = 8 et b = 13

C- a = 5 et b = 8

D- a = 13 et b = 5

(Auteur Christophe BEASSE)

Que contiennent les variables a et b si on execute ce script ?

def func(a):
    a += 2.0
    return a 
a = 5.0 
b = func(a)

Quelles sont les valeurs de a et b à la fin du programme ?

Réponses :

A- 5.0 et 5.0

B- 5.0 et 7.0

C- 7.0 et 5.0

D- 7.0 et 7.0

Espace vidéos

Utilisation de la console EDUPYTHON :

Présentation de JUPYTER :

Les fonctions (en mode console EDUPYTHON) :

Licence Creative Commons
Les différents auteurs mettent l'ensemble du site à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International